
#ifndef SAF_HEADER_FILE_MEMPOOL_H
#define SAF_HEADER_FILE_MEMPOOL_H

namespace base
{
	template <typename T, size_t cached_objs = 8, size_t max_objs = 65536>
	class mempool
	{
	private:
		union block
		{
			uint8_t	mem[sizeof(T)];
			block *	next;
		};
	public:
		mempool():num_cached_block(0), num_allocated_block(0), cached_block(NULL)
		{
			return;
		}

		~mempool()
		{
			assert(num_cached_block == num_allocated_block);
			while  (cached_block != NULL)
			{
				block * blk = cached_block->next;
				delete cached_block;
				cached_block = blk;
			}
			num_cached_block = 0;
			num_allocated_block = 0;
		}

	public:
		T * get()
		{
			T * ptr = NULL;
			if (num_cached_block > 0)
			{
				block * blk = cached_block->next;
				ptr = new (cached_block->mem) T();
				cached_block = blk;
				num_cached_block--;
			}
			else if (num_allocated_block < max_objs)
			{
				block * blk = new block;
				ptr = new (blk->mem) T();
				num_allocated_block++;
			}
			return ptr;
		}

		void put(T* obj)
		{
			if (obj != NULL)
			{
				obj->~T();
				if (num_cached_block < cached_objs)
				{
					block * blk = (block*)obj;
					blk->next = cached_block;
					cached_block = blk;
					num_cached_block++;
				}
				else
				{
					delete (block*)obj;
					num_allocated_block--;
				}
			}
		}
	private:
		size_t	num_cached_block;
		size_t	num_allocated_block;
		block *	cached_block;
	private:
		mempool(const mempool&);
		mempool& operator=(const mempool&);
	};
}

#endif
